package com.foreknow.spring;

import com.foreknow.model.Admin;
import com.foreknow.service.AdminService;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.JDOMException;
import org.jdom2.input.SAXBuilder;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * IOC容器
 */
public class ClassPathXmlApplicationContext implements BeanFactory {
    //创建一个容器
    private Map<String,Object> beans = new HashMap<>();
    //解析xml文件
    public ClassPathXmlApplicationContext() throws JDOMException, IOException, ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
        //创建一个解析器
        SAXBuilder builder = new SAXBuilder();
        //构造文档
        Document document = builder.build(this.getClass().getClassLoader().getResourceAsStream("beans.xml"));
        //获取到根节点
        Element root = document.getRootElement();
        //获取到子节点
        List<Element> list = root.getChildren();
        for(int i = 0;i<list.size();i++){
            Element element = list.get(i);
            //获取到id的值
            String id = element.getAttributeValue("id");
            String clazz = element.getAttributeValue("class");
            //需要将clazz转换为对象
            Object o = Class.forName(clazz).newInstance();
            //要将获取到的对象保存到Map容器中
            beans.put(id,o);
            for(Element propertyElement:(List<Element>)element.getChildren()){
                String name =  propertyElement.getAttributeValue("name");//adminDao
                String bean = propertyElement.getAttributeValue("bean");//u
                //从map中获取到u所对应的对象(AdminDaoImpl对象)
                Object beanObject = beans.get(bean);
                //模拟拼接一个方法setAdminDao
                String methodName = "set"+name.substring(0,1).toUpperCase()+name.substring(1); //setAdminDao
                //获取AdminService对象中的setAdminDao方法名后期可以使用invoke调用该方法
                //o指向的是AdminSerice对象
                //beanObject.getClass().getInterfaces() 获取到AdminDaoImpl对象所对应的接口 AdminDao
                Method method = o.getClass().getMethod(methodName,beanObject.getClass().getInterfaces()[0]);
                //调用method中的invoke方法来调用setAdminDao方法
                //第一个参数是要指向你要调用方法所属的对象  o所指向的是AdminService对象  beanObject指向的是AdminDaoImpl对象
                method.invoke(o,beanObject);
            }
        }
    }
    @Override
    public Object getBean(String id) {
        return beans.get(id);
    }

    public static void main(String[] args) throws JDOMException, IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {

        BeanFactory beanFactory = new ClassPathXmlApplicationContext();
        AdminService service = (AdminService) beanFactory.getBean("adminService");
        service.save(new Admin());
    }
}
